﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.Contracts;
using System.IO;
using System.Windows;
using OpenLS.Spreadsheet.Formats.Biff.OfficeArt;
using OpenLS.Spreadsheet.Formats.Biff.Records;
using OpenLS.Spreadsheet.Internals;

namespace OpenLS.Spreadsheet.Formats.Biff.Records
{
    class TxoRuns
    {
        private List<TxoRun> rgTxoRuns = new List<TxoRun>();
        private TxOLastRun lastRun;

        public TxoRuns(RichTextParagraph text, OfficeArtWriteContext context)
        {
            ushort fontId = 0;
            ushort charIndex = 0;
            foreach (var item in text.Runs)
            {
                Font font = GetFont(item);
                rgTxoRuns.Add(new TxoRun(new FormatRun(charIndex, context.GetFontId (font))));
                charIndex += (ushort)item.Text.Length;
            }
            lastRun = new TxOLastRun(charIndex);
        }

        public static  Font GetFont(RichTextRun item)
        {
            Font result = new Font();
#if DEBUG
            result.UnFreeze();
#endif
            result.FontFamily = item.FontFamily;
            if (item.IsBold)
                result.FontWeight = FontWeights.Bold;
            if (item.IsItalic)
                result.FontStyle = FontStyles.Italic;
            result.Size = item.FontSize;
            result.Foreground = item.Foreground;
            if (item.FontFamily != null)
                result.Name = result.FontFamily.Source;
#if DEBUG
            result.Freeze();
#endif
            return result;
        }

        public TxoRuns()
        {
        }



        public ushort TotalByteLength
        {
            get { return (ushort) (rgTxoRuns.Count*8 + 8); }
        }

        public void Read(MultiBinaryReader reader, int runCount)
        {
            Contract.Requires(runCount > 0);
            for (int i = 0; i < runCount; i++)
            {
                TxoRun run = new TxoRun();
                run.Read(reader);
                this.rgTxoRuns.Add(run);

            }
            this.lastRun = new TxOLastRun();
            lastRun.Read(reader);

        }

        internal struct RunInfo
        {
            public RunInfo(int startIndex, int endIndex, ushort fontIndex)
            {
                this.StartIndex = startIndex;
                this.EntIndex = endIndex;
                this.FontId = fontIndex;
            }
            public int Length { get { return this.EntIndex - this.StartIndex; } }
            public readonly int StartIndex;
            public readonly int EntIndex;
            public readonly ushort FontId;

        }

        internal IEnumerable<RunInfo> GetIndicePairs()
        {
            var previousItem = rgTxoRuns[0];
            int i = previousItem.Index;
            
            foreach (var item in Enumerable.Skip(rgTxoRuns, 1))
            {
                yield return new RunInfo(i, item.Index, previousItem.FontId); 
                //new Pair<int, int>(i, item.Index);
                i = item.Index;
                previousItem = item;
            }
            yield return new RunInfo(i, this.lastRun.Index, previousItem.FontId);
        }

        public void Write(BinaryWriter writer)
        {
#if DEBUG
            var position = writer.BaseStream.Position;
#endif
            foreach (var item in rgTxoRuns)
                item.Write(writer);
            lastRun.Write(writer);
#if DEBUG
            Contract.Assert(writer.BaseStream.Position - position == TotalByteLength);
#endif
        }

        public void ReadMulti(MultiBinaryReader readers, int runCount)
        {
            Contract.Requires(runCount > 0);
            for (int i = 0; i < runCount; i++)
            {
                TxoRun run = new TxoRun();
                run.Read(readers);
                this.rgTxoRuns.Add(run);

            }
            this.lastRun = new TxOLastRun();
            lastRun.Read(readers);
        }
    }
}